#include "instructionparser.h"

ERROR parse(const vector<InstructionParseEntry> &instructionParseList) // 目前仅将label加入符号表中
{
    for (InstructionParseEntry entry : instructionParseList)
    {
        string instruction = entry.instruction;
        vector<string> &operands = entry.operands;
        INSTRUCTION code = instructionTable.at(instruction).code;
        if (code >= JMP && code <= JLE) // 若是跳转指令
        {
            if (symbolTable.find(operands[1]) == symbolTable.end()) // 没找到这个label ,加入符号表
            {
                symbolTable[operands[1]] = {operands[1], LABEL, address++};
            }
        }
    }
    return NO_ERROR;
}

ERROR translateInstruction(const string &instruction, const vector<string> &operands, map<string, SymbolTableEntry> &symbolTable, ofstream &outputFile)
{
    if (instructionTable.find(instruction) == instructionTable.end())
    {
        // 处理指令错误
        return INSTRUCTION_NO_FIND;
    }

    InstructionTableEntry tableEntry = instructionTable.at(instruction);

    if (operands.size() != tableEntry.nums)
        // 处理操作数数量错误
        return INSTRUCTION_NUMS_ERROR;

    // 根据指令和操作数翻译成目标代码，并写入输出文件
    // ...

    outputFile << _2_16 << tableEntry.code << " ";
    // 检测操作数类型
    if (registerTable.find(operands[0]) != registerTable.end()) // 如果操作的是寄存器
    {
        outputFile << _2_16 << registerTable.at(operands[0]).reg << " ";
    }
    else if (symbolTable.find(operands[0]) != symbolTable.end()) // 如果操作的是符号表里的变量
    {
        outputFile << _2_16 << symbolTable.at(operands[0]).address << " ";
    }
    else // 操作数类型错误
    {
        return OPERAND_TYPE_ERROR;
    }
    if (operands.size() == 2) // 有两个操作数
    {
        if (registerTable.find(operands[1]) != registerTable.end()) // 如果操作的是寄存器
        {
            outputFile << _2_16 << registerTable.at(operands[1]).reg << " ";
        }
        else if (symbolTable.find(operands[1]) != symbolTable.end()) // 如果操作的是符号表里的变量
        {
            outputFile << _2_16 << symbolTable.at(operands[1]).address << " ";
        }
        else if (isArg(operands[1]) == true) // 操作的是个立即数
        {
            outputFile << _2_16 << (int)getDouble(operands[1]) << " ";
        }
        else
        {
            return OPERAND_TYPE_ERROR;
        }
    }
    return NO_ERROR;
}

ERROR second_parse(const vector<InstructionParseEntry> &instructionParseList, string outputFileName)
{
    ofstream outputFile(outputFileName, ios::trunc);
    if (!outputFile.is_open())
        return OPENING_ERROR;
    for (InstructionParseEntry entry : instructionParseList)
    {
        string instruction = entry.instruction;
        vector<string> &operands = entry.operands;

        ERROR error = translateInstruction(instruction, operands, symbolTable, outputFile);
        if (error != NO_ERROR)
        {
            outputFile.close();
            return error;
        }
    }
    outputFile.close();
    return NO_ERROR;
}
